import os
import uuid
from datetime import datetime

from flask import Flask, request, render_template_string, jsonify, session, redirect, url_for
from history import HistoryMemory  # 确保history.py是PyMySQL版HistoryMemory
import time
import random
from agent2 import EnterpriseAgentSystem  # 保持原Agent逻辑
# 替换数据库驱动：用PyMySQL替代mysql-connector
import pymysql
from pymysql import OperationalError, ProgrammingError
import bcrypt
import re


# ------------------------------
# 用户认证类（适配PyMySQL）
# ------------------------------
class UserAuth:
    def __init__(self, host, database, user, password):
        self.host = host
        self.database = database
        self.user = user
        self.password = password
        self.connection = None
        self.cursor = None

    def connect(self):
        """建立PyMySQL连接（替换mysql.connector）"""
        try:
            self.connection = pymysql.connect(
                host=self.host,
                database=self.database,
                user=self.user,
                password=self.password,
                charset='utf8mb4',  # 统一字符集
                cursorclass=pymysql.cursors.DictCursor  # 字典游标，与HistoryMemory一致
            )
            self.cursor = self.connection.cursor()
            return True
        except OperationalError as e:
            print(f"❌ 数据库连接错误: {str(e)}")
        return False

    def disconnect(self):
        """关闭PyMySQL连接"""
        if self.connection and self.connection.open:
            self.cursor.close()
            self.connection.close()

    def create_table(self):
        """创建用户表（纯单行SQL，无反斜杠）"""
        if not (self.connection and self.connection.open):
            if not self.connect():
                return False

        try:
            # 纯单行SQL，避免解析错误（适配PyMySQL）
            create_table_query = "CREATE TABLE IF NOT EXISTS users (id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(50) NOT NULL UNIQUE, email VARCHAR(100) NOT NULL UNIQUE, password_hash VARCHAR(255) NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, last_login TIMESTAMP NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;"
            self.cursor.execute(create_table_query)
            self.connection.commit()
            print("✅ 用户表初始化成功（PyMySQL）")
            return True
        except ProgrammingError as e:
            print(f"❌ 创建用户表错误: {str(e)}")
            return False

    def validate_email(self, email):
        """验证邮箱格式（逻辑不变）"""
        pattern = r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$'
        return re.match(pattern, email) is not None

    def validate_password(self, password):
        """验证密码强度（逻辑不变）"""
        if len(password) < 8:
            return False, "密码必须至少8位"
        if not re.search(r'[A-Za-z]', password):
            return False, "密码必须包含字母"
        if not re.search(r'[0-9]', password):
            return False, "密码必须包含数字"
        return True, ""

    def register(self, username, email, password):
        """用户注册（适配PyMySQL）"""
        if not (self.connection and self.connection.open):
            if not self.connect():
                return False, "无法连接到数据库"

        # 基础验证
        if not username or not email or not password:
            return False, "所有字段都是必填的"
        if len(username) < 5 or len(username) > 20:
            return False, "用户名必须为5-20个字符"
        if not self.validate_email(email):
            return False, "无效的邮箱格式"
        pass_valid, pass_msg = self.validate_password(password)
        if not pass_valid:
            return False, pass_msg

        try:
            # 检查用户名是否存在（PyMySQL参数绑定）
            self.cursor.execute("SELECT id FROM users WHERE username = %s", (username,))
            if self.cursor.fetchone():
                return False, "用户名已存在"

            # 检查邮箱是否存在（PyMySQL参数绑定）
            self.cursor.execute("SELECT id FROM users WHERE email = %s", (email,))
            if self.cursor.fetchone():
                return False, "邮箱已被注册"

            # 密码哈希（逻辑不变）
            password_hash = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())

            # 插入新用户（纯单行SQL，适配PyMySQL）
            insert_query = "INSERT INTO users (username, email, password_hash) VALUES (%s, %s, %s)"
            self.cursor.execute(insert_query, (username, email, password_hash.decode('utf-8')))
            self.connection.commit()
            return True, "注册成功，请登录"

        except ProgrammingError as e:
            self.connection.rollback()
            return False, f"注册失败: {str(e)}"

    def login(self, username, password):
        """用户登录（适配PyMySQL）"""
        if not (self.connection and self.connection.open):
            if not self.connect():
                return False, "无法连接到数据库", None

        try:
            # 支持用户名/邮箱登录（PyMySQL参数绑定）
            self.cursor.execute("SELECT * FROM users WHERE username = %s OR email = %s", (username, username))
            user = self.cursor.fetchone()

            if not user:
                return False, "用户名或邮箱不存在", None

            # 密码验证（逻辑不变）
            if bcrypt.checkpw(password.encode('utf-8'), user['password_hash'].encode('utf-8')):
                # 更新最后登录时间（PyMySQL参数绑定）
                self.cursor.execute("UPDATE users SET last_login = CURRENT_TIMESTAMP WHERE id = %s", (user['id'],))
                self.connection.commit()

                # 返回安全用户信息（不含密码）
                safe_user = {
                    'id': user['id'],
                    'username': user['username'],
                    'email': user['email'],
                    'created_at': user['created_at'].strftime("%Y-%m-%d %H:%M:%S") if user['created_at'] else None,
                    'last_login': user['last_login'].strftime("%Y-%m-%d %H:%M:%S") if user['last_login'] else None
                }
                return True, "登录成功", safe_user
            else:
                return False, "密码错误", None

        except ProgrammingError as e:
            return False, f"登录失败: {str(e)}", None

    def get_user_by_id(self, user_id):
        """通过ID获取用户（适配PyMySQL）"""
        if not (self.connection and self.connection.open):
            if not self.connect():
                return None

        try:
            # PyMySQL参数绑定（确保user_id为整数）
            self.cursor.execute("SELECT id, username, email, created_at, last_login FROM users WHERE id = %s", (int(user_id),))
            user = self.cursor.fetchone()
            if user:
                # 格式化时间戳（避免datetime对象序列化问题）
                user['created_at'] = user['created_at'].strftime("%Y-%m-%d %H:%M:%S") if user['created_at'] else None
                user['last_login'] = user['last_login'].strftime("%Y-%m-%d %H:%M:%S") if user['last_login'] else None
            return user
        except (ProgrammingError, ValueError) as e:
            print(f"❌ 获取用户信息错误: {str(e)}")
            return None


# ------------------------------
# 应用初始化（适配PyMySQL）
# ------------------------------
app = Flask(__name__)
app.secret_key = os.environ.get("SECRET_KEY", "your_secure_secret_key_2024_update_this")  # 生产环境需修改
app.config['PERMANENT_SESSION_LIFETIME'] = 3600 * 24  # Session有效期24小时

# 数据库配置（与HistoryMemory共享，统一驱动）
DB_CONFIG = {
    'host': os.environ.get('DB_HOST', 'localhost'),
    'database': os.environ.get('DB_NAME', 'user_auth_db'),
    'user': os.environ.get('DB_USER', 'root'),
    'password': os.environ.get('DB_PASSWORD', 'ht2025')  # 替换为实际密码
}

# 初始化核心组件（统一PyMySQL驱动）
auth_system = UserAuth(**DB_CONFIG)  # 现在UserAuth用PyMySQL
history_memory = HistoryMemory(  # HistoryMemory已适配PyMySQL
    db_config=DB_CONFIG,
    max_sessions=20,
    max_turns_per_session=30
)

# 初始化Agent（原逻辑不变）
FAISS_INDEX_PATH = "faiss_index"  # 替换为实际FAISS路径
try:
    enterprise_agent = EnterpriseAgentSystem(faiss_index_path=FAISS_INDEX_PATH)
    print("✅ EnterpriseAgentSystem 初始化成功")
except Exception as e:
    print(f"❌ EnterpriseAgentSystem 初始化失败: {e}")
    enterprise_agent = None

# 确保用户表存在（启动时执行）
if auth_system.connect():
    auth_system.create_table()
    auth_system.disconnect()


# ------------------------------
# 辅助函数（逻辑不变，仅适配参数类型）
# ------------------------------
def is_user_logged_in():
    """检查登录状态（确保user_id为整数）"""
    return 'user_id' in session and isinstance(session['user_id'], int) and session['user_id'] > 0


def get_current_user():
    """获取当前用户（适配PyMySQL返回的时间格式）"""
    if not is_user_logged_in():
        return None
    if auth_system.connect():
        user = auth_system.get_user_by_id(session['user_id'])
        auth_system.disconnect()
        return user
    return None


def real_agent_execute(query, context=""):
    """Agent执行（原逻辑不变）"""
    if not enterprise_agent:
        return "❌ Agent 系统未初始化，请检查日志。"
    try:
        full_query = f"请基于以下对话历史和文档知识回答问题。\n\n对话历史:\n{context}\n\n问题:\n{query}"
        agent_response = enterprise_agent.execute_query(full_query, user_react=True)
        return agent_response
    except Exception as e:
        print(f"Agent 执行出错: {e}")
        return f"❌ 执行查询时发生错误: {str(e)}"


def mock_agent_execute(query, context=""):
    """模拟Agent（开发测试用）"""
    time.sleep(0.5)
    context_summary = context.split('\n')[-2:] if context else ["无上下文"]
    context_str = " ".join(context_summary)[:50]
    greetings = ["你好", "明白了", "收到"]
    responses = [
        f"{random.choice(greetings)}！关于'{query}'，结合之前的对话({context_str}...)，我认为...",
        f"根据你的问题 '{query}' 和我们之前的交流，我的看法是...",
        f"查询 '{query}' 已处理。参考上下文: {context_str}...，答案是..."
    ]
    return random.choice(responses)


# ------------------------------
# HTML模板（无修改，保持原UI）
# ------------------------------
CHAT_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>低空导航知识库</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        secondary: '#36CFC9',
                        neutral: {
                            100: '#F5F7FA',
                            200: '#E5E6EB',
                            300: '#C9CDD4',
                            400: '#86909C',
                            500: '#4E5969',
                            600: '#272E3B',
                            700: '#1D2129',
                        },
                        success: '#00B42A',
                        danger: '#F53F3F',
                        info: '#165DFF',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                    boxShadow: {
                        'card': '0 2px 14px 0 rgba(0, 0, 0, 0.06)',
                        'hover': '0 6px 20px 0 rgba(0, 0, 0, 0.08)',
                    }
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .scrollbar-hide {
                -ms-overflow-style: none;
                scrollbar-width: none;
            }
            .scrollbar-hide::-webkit-scrollbar {
                display: none;
            }
            .text-balance {
                text-wrap: balance;
            }
        }
    </style>
</head>
<body class="font-inter bg-neutral-100 text-neutral-700 h-screen flex flex-col overflow-hidden">
    <!-- 顶部导航栏 -->
    <header class="bg-white shadow-sm border-b border-neutral-200 z-10">
        <div class="container mx-auto px-4 py-3 flex items-center justify-between">
            <div class="flex items-center space-x-3">
                <i class="fa fa-compass text-primary text-2xl"></i>
                <h1 class="text-[clamp(1.2rem,3vw,1.5rem)] font-semibold text-neutral-700">低空导航知识库</h1>
            </div>
            <div class="flex items-center space-x-4">
                <!-- 用户信息/登录注册入口 -->
                <div class="flex items-center space-x-3">
                    {% if user %}
                        <div class="relative group">
                            <button class="flex items-center space-x-2 text-neutral-700 hover:text-primary transition-colors">
                                <i class="fa fa-user-circle-o text-lg"></i>
                                <span class="hidden md:inline font-medium">{{ user.username }}</span>
                                <i class="fa fa-angle-down text-xs"></i>
                            </button>
                            <div class="absolute right-0 mt-1 w-56 bg-white rounded-lg shadow-lg py-2 hidden group-hover:block z-50 border border-neutral-200 relative transition-all duration-200 pointer-events-auto">
                                <a href="#" class="block px-4 py-2 text-sm text-neutral-700 hover:bg-neutral-100">
                                    <i class="fa fa-user-o mr-2"></i>个人中心
                                </a>
                                <a href="{{ url_for('logout') }}" class="block px-4 py-2 text-sm text-danger hover:bg-neutral-100">
                                    <i class="fa fa-sign-out mr-2"></i>退出登录
                                </a>
                            </div>
                        </div>
                    {% else %}
                        <a href="{{ url_for('login') }}" class="text-neutral-500 hover:text-primary transition-colors">
                            <i class="fa fa-sign-in mr-1"></i>登录
                        </a>
                        <a href="{{ url_for('register') }}" class="bg-primary hover:bg-primary/90 text-white rounded-lg py-1.5 px-3 text-sm transition-colors">
                            注册
                        </a>
                    {% endif %}
                </div>
                <button class="text-neutral-500 hover:text-primary transition-colors">
                    <i class="fa fa-question-circle"></i>
                </button>
                <button class="text-neutral-500 hover:text-primary transition-colors">
                    <i class="fa fa-cog"></i>
                </button>
            </div>
        </div>
    </header>

    <div class="flex flex-1 overflow-hidden">
        <!-- 左侧边栏 - 会话列表 -->
        <aside class="w-72 bg-white border-r border-neutral-200 flex flex-col hidden md:flex transition-all duration-300 ease-in-out" id="sidebar">
            <div class="p-4 border-b border-neutral-200">
                <div class="flex items-center justify-between mb-2">
                    <h2 class="font-medium text-neutral-700">会话历史</h2>
                    <span class="text-xs bg-primary/10 text-primary px-2 py-0.5 rounded-full" id="session-count">0 个会话</span>
                </div>
                <button id="new-session-btn" class="w-full bg-primary hover:bg-primary/90 text-white rounded-lg py-2.5 px-4 flex items-center justify-center space-x-2 transition-all duration-200 shadow-sm hover:shadow">
                    <i class="fa fa-plus text-sm"></i>
                    <span>新建会话</span>
                </button>
            </div>

            <div class="flex-1 overflow-y-auto scrollbar-hide p-2" id="session-list">
                <!-- 会话列表将通过 JS 动态填充 -->
                <div class="text-neutral-400 text-center py-10">
                    <i class="fa fa-comments-o text-4xl mb-3 opacity-30"></i>
                    <p>暂无会话记录</p>
                </div>
            </div>

            <div class="p-3 border-t border-neutral-200">
                <button id="clear-all-sessions-btn" class="w-full text-neutral-500 hover:text-primary text-sm py-2 flex items-center justify-center transition-colors duration-200">
                    <i class="fa fa-trash-o mr-2"></i>
                    清除所有会话
                </button>
            </div>
        </aside>

        <!-- 移动端侧边栏切换按钮 -->
        <button id="sidebar-toggle" class="md:hidden fixed left-4 bottom-20 bg-primary text-white rounded-full w-12 h-12 flex items-center justify-center shadow-lg z-20">
            <i class="fa fa-bars"></i>
        </button>

        <!-- 右侧主内容区 -->
        <main class="flex-1 flex flex-col overflow-hidden">
            <!-- 聊天历史区域 -->
            <div class="flex-1 overflow-y-auto p-4 md:p-6 bg-neutral-50 scrollbar-hide" id="chat-history">
                <!-- 对话历史将通过 JS 动态填充 -->
                <div class="max-w-3xl mx-auto mb-8 mt-4">
                    <div class="agent-message bg-white rounded-xl p-4 shadow-card border border-neutral-200 mb-6 inline-block">
                        <div class="flex items-center mb-2">
                            <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                                <i class="fa fa-robot"></i>
                            </div>
                            <span class="font-medium text-neutral-700">助手</span>
                        </div>
                        <div class="text-neutral-600 text-balance">你好！我是低空导航知识库助手。请选择一个会话或新建一个会话开始对话。</div>
                    </div>
                </div>
            </div>

            <!-- 输入区域 -->
            <div class="border-t border-neutral-200 bg-white p-4 md:p-6">
                <div class="max-w-3xl mx-auto">
                    <div class="relative">
                        <textarea 
                            id="user-input" 
                            placeholder="输入你的问题..." 
                            class="w-full px-4 py-3 pr-12 rounded-xl border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all duration-200 resize-none min-h-[60px] max-h-[200px] scrollbar-hide"
                            autocomplete="off"
                        ></textarea>
                        <button id="send-btn" class="absolute right-3 bottom-3 bg-primary hover:bg-primary/90 text-white rounded-full w-9 h-9 flex items-center justify-center transition-all duration-200 shadow-sm hover:shadow">
                            <i class="fa fa-paper-plane-o"></i>
                        </button>
                    </div>
                    <p class="text-xs text-neutral-400 mt-2 text-center">
                        提示：输入问题后按Enter发送，Shift+Enter换行
                    </p>
                </div>
            </div>
        </main>
    </div>

    <script>
        // 全局变量
        let currentSessionId = null;

        // DOM 元素
        const sessionListElement = document.getElementById('session-list');
        const chatHistoryElement = document.getElementById('chat-history');
        const userInputElement = document.getElementById('user-input');
        const sendButtonElement = document.getElementById('send-btn');
        const newSessionButton = document.getElementById('new-session-btn');
        const sessionCountElement = document.getElementById('session-count');
        const sidebarElement = document.getElementById('sidebar');
        const sidebarToggleElement = document.getElementById('sidebar-toggle');
        const clearAllBtn = document.getElementById('clear-all-sessions-btn');

        // --- 辅助函数 ---
        function formatTime(timestampStr) {
            const date = new Date(timestampStr);
            return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' });
        }

        function formatDate(timestampStr) {
            const date = new Date(timestampStr);
            const now = new Date();
            const yesterday = new Date(now);
            yesterday.setDate(yesterday.getDate() - 1);

            if (date.toDateString() === now.toDateString()) {
                return '今天 ' + formatTime(timestampStr);
            } else if (date.toDateString() === yesterday.toDateString()) {
                return '昨天 ' + formatTime(timestampStr);
            } else {
                return date.toLocaleDateString('zh-CN') + ' ' + formatTime(timestampStr);
            }
        }

        function scrollToBottom() {
            chatHistoryElement.scrollTop = chatHistoryElement.scrollHeight;
        }

        function showLoading() {
            const loadingElement = document.createElement('div');
            loadingElement.className = 'max-w-3xl mx-auto mb-6';
            loadingElement.innerHTML = `
                <div class="agent-message bg-white rounded-xl p-4 shadow-card border border-neutral-200 inline-block">
                    <div class="flex items-center mb-2">
                        <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                            <i class="fa fa-robot"></i>
                        </div>
                        <span class="font-medium text-neutral-700">助手</span>
                    </div>
                    <div class="flex space-x-1">
                        <div class="w-2 h-2 bg-neutral-400 rounded-full animate-bounce" style="animation-delay: 0ms"></div>
                        <div class="w-2 h-2 bg-neutral-400 rounded-full animate-bounce" style="animation-delay: 150ms"></div>
                        <div class="w-2 h-2 bg-neutral-400 rounded-full animate-bounce" style="animation-delay: 300ms"></div>
                    </div>
                </div>
            `;
            loadingElement.id = 'loading-indicator';
            chatHistoryElement.appendChild(loadingElement);
            scrollToBottom();
            sendButtonElement.disabled = true;
            userInputElement.disabled = true;
        }

        function hideLoading() {
            const loadingElement = document.getElementById('loading-indicator');
            if (loadingElement) {
                loadingElement.remove();
            }
            sendButtonElement.disabled = false;
            userInputElement.disabled = false;
            userInputElement.focus();
        }

        // --- API 调用函数 ---
        async function fetchSessions() {
            try {
                const response = await fetch('/api/sessions', { method: 'GET' });
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const sessions = await response.json();
                renderSessionList(sessions);
                sessionCountElement.textContent = `${sessions.length} 个会话`;
            } catch (error) {
                console.error('获取会话列表失败:', error);
            }
        }

        async function clearAllSessions() {
            const confirmClear = confirm("确定要清除所有会话历史吗？此操作不可恢复！");
            if (!confirmClear) return;

            try {
                const response = await fetch('/api/clear_all_sessions', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' }
                });
                const data = await response.json();

                if (data.status === 'success') {
                    alert(data.message);
                    currentSessionId = null;
                    await fetchSessions();
                    fetchChatHistory(null);
                } else {
                    alert(`清空失败: ${data.message}`);
                }
            } catch (error) {
                console.error('清空会话出错:', error);
                alert('清空会话时发生网络错误，请重试！');
            }
        }

        async function fetchChatHistory(sessionId) {
            if (!sessionId) {
                chatHistoryElement.innerHTML = `
                    <div class="max-w-3xl mx-auto mb-8 mt-4">
                        <div class="agent-message bg-white rounded-xl p-4 shadow-card border border-neutral-200 mb-6 inline-block">
                            <div class="flex items-center mb-2">
                                <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                                    <i class="fa fa-robot"></i>
                                </div>
                                <span class="font-medium text-neutral-700">助手</span>
                            </div>
                            <div class="text-neutral-600">${marked.parse('请选择一个会话或新建一个会话。')}</div>
                        </div>
                    </div>
                `;
                return;
            }
            try {
                const response = await fetch(`/api/history/${sessionId}`, { method: 'GET' });
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const history = await response.json();
                renderChatHistory(history);
            } catch (error) {
                console.error('获取聊天历史失败:', error);
                chatHistoryElement.innerHTML = `
                    <div class="max-w-3xl mx-auto mb-8 mt-4">
                        <div class="agent-message bg-white rounded-xl p-4 shadow-card border border-neutral-200 mb-6 inline-block">
                            <div class="flex items-center mb-2">
                                <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                                    <i class="fa fa-robot"></i>
                                </div>
                                <span class="font-medium text-neutral-700">助手</span>
                            </div>
                            <div class="text-neutral-600">${marked.parse('加载聊天历史失败。')}</div>
                        </div>
                    </div>
                `;
            }
        }

        async function sendMessage(message, sessionId) {
            if (!message || !sessionId) return;

            // 显示用户消息
            addMessageToChat('user', message, new Date().toISOString());
            // 显示加载指示器
            showLoading();

            try {
                const response = await fetch('/api/chat', {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({ message: message, session_id: sessionId })
                });

                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const data = await response.json();

                hideLoading();
                addMessageToChat('agent', data.response, data.timestamp);
                await fetchSessions();

            } catch (error) {
                console.error('发送消息失败:', error);
                hideLoading();
                addMessageToChat('agent', '抱歉，发送消息时出错。', new Date().toISOString());
            }
        }

        async function createNewSession() {
            try {
                const response = await fetch('/api/new_session', { method: 'POST' });
                if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
                const data = await response.json();
                const newSessionId = data.session_id;

                currentSessionId = newSessionId;
                await fetchSessions();
                await fetchChatHistory(currentSessionId);

                if (window.innerWidth < 768) {
                    toggleSidebar();
                }

            } catch (error) {
                console.error('创建新会话失败:', error);
                alert('创建新会话失败。');
            }
        }

        function toggleSidebar() {
            sidebarElement.classList.toggle('hidden');
            sidebarElement.classList.toggle('absolute');
            sidebarElement.classList.toggle('inset-0');
            sidebarElement.classList.toggle('z-30');
            sidebarElement.classList.toggle('w-full');
        }

        // --- 渲染函数 ---
        function renderSessionList(sessions) {
            sessionListElement.innerHTML = '';
            if (sessions.length === 0) {
                sessionListElement.innerHTML = `
                    <div class="text-neutral-400 text-center py-10">
                        <i class="fa fa-comments-o text-4xl mb-3 opacity-30"></i>
                        <p>暂无会话记录</p>
                    </div>
                `;
                return;
            }

            sessions.sort((a, b) => new Date(b.timestamp) - new Date(a.timestamp));

            sessions.forEach(session => {
                const sessionElement = document.createElement('div');
                sessionElement.className = `session-item rounded-lg p-3 mb-1 cursor-pointer transition-all duration-200 ${session.id === currentSessionId ? 'bg-primary/5 border-l-4 border-primary' : 'hover:bg-neutral-50'}`;
                sessionElement.dataset.sessionId = session.id;

                let displayTitle = session.title.length > 30 ? session.title.substring(0, 30) + '...' : session.title;

                sessionElement.innerHTML = `
                    <div class="flex justify-between items-start">
                        <div class="font-medium text-neutral-700 text-sm truncate max-w-[160px]">${displayTitle}</div>
                        <span class="text-xs text-neutral-400">${formatTime(session.timestamp)}</span>
                    </div>
                    <div class="text-xs text-neutral-500 mt-1 line-clamp-1">${formatDate(session.timestamp)}</div>
                `;

                sessionElement.addEventListener('click', () => {
                    currentSessionId = session.id;
                    document.querySelectorAll('.session-item').forEach(item => {
                        item.classList.remove('bg-primary/5', 'border-l-4', 'border-primary');
                        item.classList.add('hover:bg-neutral-50');
                    });
                    sessionElement.classList.add('bg-primary/5', 'border-l-4', 'border-primary');
                    sessionElement.classList.remove('hover:bg-neutral-50');
                    fetchChatHistory(currentSessionId);

                    if (window.innerWidth < 768) {
                        toggleSidebar();
                    }
                });

                sessionListElement.appendChild(sessionElement);
            });
        }

        function renderChatHistory(history) {
            chatHistoryElement.innerHTML = '';
            if (history.length === 0) {
                chatHistoryElement.innerHTML = `
                    <div class="max-w-3xl mx-auto mb-8 mt-4">
                        <div class="agent-message bg-white rounded-xl p-4 shadow-card border border-neutral-200 mb-6 inline-block">
                            <div class="flex items-center mb-2">
                                <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                                    <i class="fa fa-robot"></i>
                                </div>
                                <span class="font-medium text-neutral-700">助手</span>
                            </div>
                            <div class="text-neutral-600">${marked.parse('开始对话吧！')}</div>
                        </div>
                    </div>
                `;
                scrollToBottom();
                return;
            }

            history.forEach(turn => {
                addMessageToChat('user', turn.user, turn.timestamp);
                addMessageToChat('agent', turn.agent, turn.timestamp);
            });
            scrollToBottom();
        }

        function addMessageToChat(sender, content, timestamp) {
            const messageContainer = document.createElement('div');
            messageContainer.className = `max-w-3xl mx-auto mb-6 animate-fadeIn`;

            const timeStr = formatTime(timestamp);
            const isUser = sender === 'user';
            const parsedContent = marked.parse(content);

            messageContainer.innerHTML = `
                <div class="${isUser ? 'flex justify-end' : ''}">
                    <div class="${isUser ? 'user-message bg-primary text-white' : 'agent-message bg-white border border-neutral-200 text-neutral-700'} rounded-xl p-4 shadow-card max-w-[85%]">
                        <div class="flex ${isUser ? 'justify-between' : 'items-center'} mb-2">
                            ${!isUser ? `
                                <div class="w-8 h-8 rounded-full bg-primary/10 flex items-center justify-center text-primary mr-3">
                                    <i class="fa fa-robot"></i>
                                </div>
                                <span class="font-medium">助手</span>
                            ` : `
                                <span class="font-medium">你</span>
                            `}
                            <span class="text-xs opacity-70">${timeStr}</span>
                        </div>
                        <div class="text-balance">${parsedContent}</div>
                    </div>
                </div>
            `;

            chatHistoryElement.appendChild(messageContainer);
            scrollToBottom();
        }

        function adjustTextareaHeight() {
            userInputElement.style.height = 'auto';
            userInputElement.style.height = (Math.min(userInputElement.scrollHeight, 200)) + 'px';
        }

        // --- 事件监听器 ---
        sendButtonElement.addEventListener('click', () => {
            const message = userInputElement.value.trim();
            if (message && currentSessionId) {
                sendMessage(message, currentSessionId);
                userInputElement.value = '';
                adjustTextareaHeight();
            } else if(!currentSessionId) {
                alert('请先选择或创建一个会话。');
            }
        });

        userInputElement.addEventListener('keydown', (e) => {
            adjustTextareaHeight();
            if (e.key === 'Enter' && !e.shiftKey) {
                e.preventDefault();
                sendButtonElement.click();
            }
        });

        newSessionButton.addEventListener('click', createNewSession);
        sidebarToggleElement.addEventListener('click', toggleSidebar);
        if (clearAllBtn) {
            clearAllBtn.addEventListener('click', clearAllSessions);
        }

        window.addEventListener('resize', () => {
            if (window.innerWidth >= 768) {
                sidebarElement.classList.remove('hidden', 'absolute', 'inset-0', 'z-30', 'w-full');
                sidebarElement.classList.add('flex');
            } else if (currentSessionId) {
                sidebarElement.classList.add('hidden');
                sidebarElement.classList.remove('absolute', 'inset-0', 'z-30', 'w-full', 'flex');
            }
        });

        // --- 初始化 ---
        window.addEventListener('DOMContentLoaded', async () => {
            await fetchSessions();
            adjustTextareaHeight();
            userInputElement.focus();
            userInputElement.addEventListener('input', adjustTextareaHeight);
        });

        // 添加淡入动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .animate-fadeIn {
                animation: fadeIn 0.3s ease-out forwards;
            }
        `;
        document.head.appendChild(style);
    </script>
</body>
</html>
"""

LOGIN_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录 - 低空导航知识库</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        neutral: {
                            100: '#F5F7FA',
                            200: '#E5E6EB',
                            300: '#C9CDD4',
                            400: '#86909C',
                            500: '#4E5969',
                            600: '#272E3B',
                            700: '#1D2129',
                        },
                        success: '#00B42A',
                        danger: '#F53F3F',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .auth-card {
                box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.08);
            }
        }
    </style>
</head>
<body class="font-inter bg-neutral-100 min-h-screen flex flex-col">
    <!-- 顶部导航 -->
    <header class="bg-white shadow-sm border-b border-neutral-200">
        <div class="container mx-auto px-4 py-3 flex items-center justify-between">
            <div class="flex items-center space-x-3">
                <i class="fa fa-compass text-primary text-2xl"></i>
                <h1 class="text-[clamp(1.2rem,3vw,1.5rem)] font-semibold text-neutral-700">低空导航知识库</h1>
            </div>
            <div>
                <a href="{{ url_for('index') }}" class="text-neutral-500 hover:text-primary transition-colors">
                    <i class="fa fa-arrow-left mr-1"></i>返回首页
                </a>
            </div>
        </div>
    </header>

    <!-- 主内容区 -->
    <main class="flex-1 flex items-center justify-center p-4 md:p-8">
        <div class="w-full max-w-md">
            <div class="bg-white rounded-2xl p-6 md:p-8 auth-card">
                <div class="text-center mb-8">
                    <h2 class="text-[clamp(1.5rem,3vw,1.8rem)] font-bold text-neutral-700 mb-2">欢迎回来</h2>
                    <p class="text-neutral-500">请登录您的账号继续使用</p>
                </div>

                <!-- 错误提示 -->
                {% if error %}
                <div class="bg-danger/10 border border-danger/20 text-danger rounded-lg p-3 mb-6 flex items-center">
                    <i class="fa fa-exclamation-circle mr-2"></i>
                    <span>{{ error }}</span>
                </div>
                {% endif %}

                <!-- 登录表单 -->
                <form method="POST" action="{{ url_for('login') }}">
                    <div class="mb-5">
                        <label for="username" class="block text-sm font-medium text-neutral-700 mb-1">用户名或邮箱</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-neutral-400">
                                <i class="fa fa-user-o"></i>
                            </span>
                            <input type="text" id="username" name="username" 
                                class="w-full pl-10 pr-4 py-3 rounded-lg border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
                                placeholder="请输入用户名或邮箱" required
                                value="{{ request.form.username if request.form.username else '' }}">
                        </div>
                    </div>

                    <div class="mb-6">
                        <div class="flex justify-between items-center mb-1">
                            <label for="password" class="block text-sm font-medium text-neutral-700">密码</label>
                            <a href="#" class="text-sm text-primary hover:text-primary/80 transition-colors">忘记密码？</a>
                        </div>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-neutral-400">
                                <i class="fa fa-lock-o"></i>
                            </span>
                            <input type="password" id="password" name="password" 
                                class="w-full pl-10 pr-4 py-3 rounded-lg border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
                                placeholder="请输入密码" required>
                        </div>
                    </div>

                    <div class="mb-8">
                        <button type="submit" 
                            class="w-full bg-primary hover:bg-primary/90 text-white font-medium rounded-lg py-3 transition-all shadow-sm hover:shadow">
                            登录
                        </button>
                    </div>

                    <div class="text-center text-neutral-500 text-sm">
                        还没有账号？<a href="{{ url_for('register') }}" class="text-primary hover:text-primary/80 font-medium transition-colors">立即注册</a>
                    </div>
                </form>
            </div>

            <!-- 底部信息 -->
            <div class="text-center text-neutral-400 text-xs mt-8">
                <p>© 2024 低空导航知识库 版权所有</p>
            </div>
        </div>
    </main>
</body>
</html>
"""

REGISTER_TEMPLATE = """
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>注册 - 低空导航知识库</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#165DFF',
                        neutral: {
                            100: '#F5F7FA',
                            200: '#E5E6EB',
                            300: '#C9CDD4',
                            400: '#86909C',
                            500: '#4E5969',
                            600: '#272E3B',
                            700: '#1D2129',
                        },
                        success: '#00B42A',
                        danger: '#F53F3F',
                    },
                    fontFamily: {
                        inter: ['Inter', 'system-ui', 'sans-serif'],
                    },
                },
            }
        }
    </script>
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .auth-card {
                box-shadow: 0 4px 20px 0 rgba(0, 0, 0, 0.08);
            }
            .password-hint {
                font-size: 0.75rem;
                line-height: 1rem;
            }
        }
    </style>
</head>
<body class="font-inter bg-neutral-100 min-h-screen flex flex-col">
    <!-- 顶部导航 -->
    <header class="bg-white shadow-sm border-b border-neutral-200">
        <div class="container mx-auto px-4 py-3 flex items-center justify-between">
            <div class="flex items-center space-x-3">
                <i class="fa fa-compass text-primary text-2xl"></i>
                <h1 class="text-[clamp(1.2rem,3vw,1.5rem)] font-semibold text-neutral-700">低空导航知识库</h1>
            </div>
            <div>
                <a href="{{ url_for('index') }}" class="text-neutral-500 hover:text-primary transition-colors">
                    <i class="fa fa-arrow-left mr-1"></i>返回首页
                </a>
            </div>
        </div>
    </header>

    <!-- 主内容区 -->
    <main class="flex-1 flex items-center justify-center p-4 md:p-8">
        <div class="w-full max-w-md">
            <div class="bg-white rounded-2xl p-6 md:p-8 auth-card">
                <div class="text-center mb-8">
                    <h2 class="text-[clamp(1.5rem,3vw,1.8rem)] font-bold text-neutral-700 mb-2">创建账号</h2>
                    <p class="text-neutral-500">填写以下信息注册低空导航知识库账号</p>
                </div>

                <!-- 错误提示 -->
                {% if error %}
                <div class="bg-danger/10 border border-danger/20 text-danger rounded-lg p-3 mb-6 flex items-center">
                    <i class="fa fa-exclamation-circle mr-2"></i>
                    <span>{{ error }}</span>
                </div>
                {% endif %}

                <!-- 成功提示 -->
                {% if success %}
                <div class="bg-success/10 border border-success/20 text-success rounded-lg p-3 mb-6 flex items-center">
                    <i class="fa fa-check-circle mr-2"></i>
                    <span>{{ success }}</span>
                </div>
                {% endif %}

                <!-- 注册表单 -->
                <form method="POST" action="{{ url_for('register') }}">
                    <div class="mb-5">
                        <label for="username" class="block text-sm font-medium text-neutral-700 mb-1">用户名</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-neutral-400">
                                <i class="fa fa-user-o"></i>
                            </span>
                            <input type="text" id="username" name="username" 
                                class="w-full pl-10 pr-4 py-3 rounded-lg border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
                                placeholder="请输入用户名（5-20个字符）" required
                                value="{{ request.form.username if request.form.username else '' }}">
                        </div>
                    </div>

                    <div class="mb-5">
                        <label for="email" class="block text-sm font-medium text-neutral-700 mb-1">邮箱</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-neutral-400">
                                <i class="fa fa-envelope-o"></i>
                            </span>
                            <input type="email" id="email" name="email" 
                                class="w-full pl-10 pr-4 py-3 rounded-lg border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
                                placeholder="请输入您的邮箱" required
                                value="{{ request.form.email if request.form.email else '' }}">
                        </div>
                    </div>

                    <div class="mb-3">
                        <label for="password" class="block text-sm font-medium text-neutral-700 mb-1">密码</label>
                        <div class="relative">
                            <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-neutral-400">
                                <i class="fa fa-lock-o"></i>
                            </span>
                            <input type="password" id="password" name="password" 
                                class="w-full pl-10 pr-4 py-3 rounded-lg border border-neutral-300 focus:border-primary focus:ring-2 focus:ring-primary/20 outline-none transition-all"
                                placeholder="请输入密码" required>
                        </div>
                    </div>

                    <div class="mb-6 text-neutral-500 password-hint">
                        <i class="fa fa-info-circle mr-1"></i>
                        密码必须至少8位，包含字母和数字
                    </div>

                    <div class="mb-8">
                        <button type="submit" 
                            class="w-full bg-primary hover:bg-primary/90 text-white font-medium rounded-lg py-3 transition-all shadow-sm hover:shadow">
                            注册
                        </button>
                    </div>

                    <div class="text-center text-neutral-500 text-sm">
                        已有账号？<a href="{{ url_for('login') }}" class="text-primary hover:text-primary/80 font-medium transition-colors">立即登录</a>
                    </div>
                </form>
            </div>

            <!-- 底部信息 -->
            <div class="text-center text-neutral-400 text-xs mt-8">
                <p>© 2024 低空导航知识库 版权所有</p>
                <p class="mt-1">注册即表示您同意我们的<a href="#" class="text-primary hover:underline">服务条款</a>和<a href="#" class="text-primary hover:underline">隐私政策</a></p>
            </div>
        </div>
    </main>
</body>
</html>
"""


# ------------------------------
# 路由配置（适配PyMySQL，确保参数类型正确）
# ------------------------------
@app.route("/")
def index():
    """主聊天页面（登录验证不变）"""
    if not is_user_logged_in():
        return redirect(url_for('login'))
    user = get_current_user()
    return render_template_string(CHAT_TEMPLATE, user=user)


@app.route("/login", methods=["GET", "POST"])
def login():
    """登录页面（适配PyMySQL返回的用户信息）"""
    if is_user_logged_in():
        return redirect(url_for('index'))

    error = ""
    if request.method == "POST":
        username = request.form.get("username", "").strip()
        password = request.form.get("password", "").strip()

        if not username or not password:
            error = "请填写完整的登录信息"
        else:
            if auth_system.connect():
                success, msg, user = auth_system.login(username, password)
                auth_system.disconnect()

                if success and user:
                    # 确保user_id为整数（适配HistoryMemory）
                    session.permanent = True
                    session['user_id'] = int(user['id'])
                    session['username'] = user['username']
                    return redirect(url_for('index'))
                else:
                    error = msg
            else:
                error = "数据库连接失败，请稍后重试"

    return render_template_string(LOGIN_TEMPLATE, error=error)


@app.route("/register", methods=["GET", "POST"])
def register():
    """注册页面（逻辑不变，适配PyMySQL）"""
    if is_user_logged_in():
        return redirect(url_for('index'))

    error = ""
    success = ""
    if request.method == "POST":
        username = request.form.get("username", "").strip()
        email = request.form.get("email", "").strip()
        password = request.form.get("password", "").strip()

        if not username or not email or not password:
            error = "请填写完整的注册信息"
        elif len(username) < 5 or len(username) > 20:
            error = "用户名必须为5-20个字符"
        else:
            if auth_system.connect():
                reg_success, reg_msg = auth_system.register(username, email, password)
                auth_system.disconnect()
                if reg_success:
                    success = reg_msg
                else:
                    error = reg_msg
            else:
                error = "数据库连接失败，请稍后重试"

    return render_template_string(REGISTER_TEMPLATE, error=error, success=success)


@app.route("/logout")
def logout():
    """登出（清除Session不变）"""
    session.clear()
    return redirect(url_for('login'))


# ------------------------------
# API 路由（适配PyMySQL，确保参数正确）
# ------------------------------
@app.before_request
def before_api_request():
    """API请求前验证登录（确保user_id为整数）"""
    excluded_routes = ['login', 'register', 'static']
    if (request.endpoint and request.endpoint.startswith('api_') and
        request.endpoint not in excluded_routes):
        if not is_user_logged_in():
            return jsonify({"error": "请先登录"}), 401


@app.route("/api/sessions", methods=["GET"])
def api_get_sessions():
    """获取会话列表（传递整数user_id）"""
    user_id = session.get('user_id')  # 已确保为整数
    sessions_list = history_memory.get_sessions_list(user_id=user_id)
    return jsonify(sessions_list)


@app.route("/api/history/<session_id>", methods=["GET"])
def api_get_history(session_id):
    """获取聊天历史（传递整数user_id）"""
    user_id = session.get('user_id')  # 已确保为整数
    history = history_memory.get_history(session_id=session_id, user_id=user_id)
    return jsonify(history)


@app.route("/api/chat", methods=["POST"])
def api_chat():
    """处理聊天消息（适配PyMySQL参数类型）"""
    user_id = session.get('user_id')  # 整数类型
    data = request.get_json()
    user_message = data.get("message", "").strip()
    session_id = data.get("session_id")

    if not user_message or not session_id:
        return jsonify({"error": "缺少消息或会话ID"}), 400

    # 获取上下文（HistoryMemory已适配PyMySQL）
    context = history_memory.get_context(session_id=session_id, user_id=user_id, last_n=3)

    # 调用Agent（原逻辑不变）
    agent_response = real_agent_execute(user_message, context=context)

    # 保存对话（传递整数user_id）
    try:
        history_memory.add_turn(
            user_input=user_message,
            agent_response=agent_response,
            session_id=session_id,
            user_id=user_id  # 整数类型，适配数据库INT字段
        )
    except Exception as e:
        return jsonify({"error": f"保存对话失败: {str(e)}"}), 500

    # 返回响应
    response_timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    return jsonify({
        "response": agent_response,
        "timestamp": response_timestamp
    })


@app.route("/api/new_session", methods=["POST"])
def api_new_session():
    """创建新会话（传递整数user_id）"""
    user_id = session.get('user_id')  # 整数类型
    new_session_id = history_memory.start_new_session(user_id=user_id)
    return jsonify({"session_id": new_session_id})


@app.route("/api/clear_all_sessions", methods=["POST"])
def api_clear_all_sessions():
    """清空所有会话（传递整数user_id）"""
    try:
        user_id = session.get('user_id')  # 整数类型
        history_memory.clear_all_sessions(user_id=user_id)
        return jsonify({"status": "success", "message": "所有会话已清空"})
    except Exception as e:
        print(f"清空会话出错: {e}")
        return jsonify({"status": "error", "message": f"清空失败: {str(e)}"}), 500


# ------------------------------
# 应用启动（适配PyMySQL）
# ------------------------------
if __name__ == "__main__":
    # 确保数据库表存在（UserAuth和HistoryMemory的表）
    if auth_system.connect():
        auth_system.create_table()
        auth_system.disconnect()

    # 启动Flask应用
    app.run(
        threaded=True,
        host="0.0.0.0",
        port=int(os.environ.get("PORT", 5000)),
        debug=False  # 生产环境禁用Debug
    )
# if __name__ == "__main__":
#     if auth_system.connect():
#         auth_system.create_table()
#         auth_system.disconnect()

# gunicorn -w 4 -b 0.0.0.0:5001 "qa_web3_3:app"